package com.celeritymq.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import com.celeritymq.configure.Base;
import com.celeritymq.handler.CelerityWriterImpl;
import com.celeritymq.handler.Handler;
import com.celeritymq.handler.Handler0;
import com.celeritymq.utils.CelerityBuffer;

public class CelerityServerImpl implements CelerityServer, Runnable {
	private Selector selector;

	CelerityServerImpl(String ip, int port) throws IOException {
		selector = Selector.open();
		ServerSocketChannel ssc = ServerSocketChannel.open();
		ssc.configureBlocking(false);
		ssc.socket().bind(new InetSocketAddress(Base.destinationIp(), Base.destinationPort()));
		ssc.register(selector, SelectionKey.OP_ACCEPT);
	}

	@Override
	public void run() {
		try {
			while (selector.select() > 0) {
				Set<SelectionKey> keys = selector.selectedKeys();
				Iterator<SelectionKey> it = keys.iterator();
//				System.out.println("acceptor: " + keys);
				while (it.hasNext()) {
					SelectionKey key = it.next();
					it.remove();
//					System.out.println("accept key: " + key);
					if (acceptable(key)) {
						accept(key);
					} else if (readable(key)) {
						read(key);
					} else if (writable(key)) {
						write(key);
					}
				}
				TimeUnit.SECONDS.sleep(2);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private boolean acceptable(SelectionKey key) {
		return key.isValid() && key.isAcceptable();
	}

	private boolean writable(SelectionKey key) {
		return key.isValid() && key.isWritable();
	}

	private boolean readable(SelectionKey key) {
		return key.isValid() && key.isReadable();
	}

	public void accept(SelectionKey key) {
		try {
			ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
			SocketChannel sc = ssc.accept();
			System.out.println("acceptor sc: " + sc);
			sc.configureBlocking(false);
			Handler handler=new Handler0();
			handler.setChannel(sc);
			SocketAddress remoteAddress=sc.socket().getRemoteSocketAddress();
			sc.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE, new Handler0());
			System.out.println("register read complete");
			System.out.println("register write complete");
			// key.attach(new CelerityBuffer());
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void read(SelectionKey key){
		Handler handler=(Handler)key.attachment();
		handler.handleIn();
	}
	
	private void write(SelectionKey key){
		
	}
}
